﻿using BuildCode.Models;
using System;
using System.Collections.Generic;
using System.Data;
using System.Data.SqlClient;
using System.Linq;
using System.Text;
using System.Web;
using System.Web.Mvc;
using System.Configuration;
using System.Xml;
using RazorEngine;
using System.IO;
using System.Reflection;
using System.Threading.Tasks;

namespace BuildCode.Controllers
{
    public class HomeController : Controller
    {
        List<ColumnInfo> StaticDataList = new List<ColumnInfo>();
        ConfigInfo StaticConfigInfo = new ConfigInfo();
        static IDataBase db = null;
        static List<string> removeCols = null;
        static string baseTemplatePath;
        static Dictionary<string, MethodInfo> dicMethod = new Dictionary<string, MethodInfo>();
        static bool IsCompiled = false;

        public ActionResult Index()
        {
            var listConnection = new ConfigHelper().ReadConnection();
            var dic = listConnection.GroupBy(t => t.Item1).ToDictionary(t => t.Key, t => t.Select(s => s.Item2));
            return View(dic);
        }

        public JsonResult GetTableList()
        {
            if (db == null)
            {
                var listConnection = new ConfigHelper().ReadConnection();
                var dataBase = new DataBaseCommon().GetDataBaseEnum(listConnection[0].Item1);
                db = new DataBaseFactory().GetDataBase(dataBase);
                db.SetConfig(listConnection[0].Item2, listConnection[0].Item3);
            }
            //db = new DataBaseFactory().GetDataBase(DataBaseEnum.PDM);
            //db.SetConfig(Server.MapPath("~/PdmFiles/"), "");
            var list = db.GetTableList();
            if (!IsCompiled)
            {
                Task.Run(() => {
                    PreCompile();
                });
            }
            return Json(list, JsonRequestBehavior.AllowGet);
        }

        public JsonResult GetTableDetail(string TableName)
        {
            var listRes = db.GetColumnList(TableName);
            foreach (var item in listRes)
            {
                if (item.ColumnName.ToUpper() == "ID")
                {
                    item.IsPK = true;
                }
                if (!GetRemoveCols().Contains(item.ColumnName))
                {
                    item.IsShow = true;
                }
            }
            return Json(listRes, JsonRequestBehavior.AllowGet);
        }

        [HttpPost]
        public string RefreshPdmTable()
        {
            db = new DataBaseFactory().GetDataBase(DataBaseEnum.PDM);
            db.SetConfig(Server.MapPath("~/PdmFiles/"), "");
            db.RefreshData();
            return "Success";
        }

        public string SetConnection(string dataType, string connection, string dataBaseName)
        {
            var check = CheckConnection(dataType, connection);
            if (check == "连接成功")
            {
                var dbCommon = new DataBaseCommon();
                var dataBase = dbCommon.GetBaseEnumByType(dataType);
                db = new DataBaseFactory().GetDataBase(dataBase);
                db.SetConfig(connection, dataBaseName);
                var provider = dbCommon.GetProvider(dataBase);
                new ConfigHelper().AddConnection(connection, provider, dataBaseName);
                return "设置成功";
            }
            return "设置失败";
        }

        /// <summary>
        /// 测试连接
        /// </summary>
        /// <returns></returns>
        public string CheckConnection(string dataType, string connection)
        {
            var dataBase = new DataBaseCommon().GetBaseEnumByType(dataType);
            var dbCheck = new DataBaseFactory().GetDataBase(dataBase);
            dbCheck.SetConfig(connection, "");
            string res = dbCheck.CheckConnection();
            return res;
        }

        public string SetData(List<ColumnInfo> DataList, ConfigInfo ConfigInfo)
        {
            try
            {
                StaticDataList = DataList != null ? DataList.Where(t => t.IsCheck == true).ToList() : StaticDataList;
                StaticConfigInfo = ConfigInfo;

                #region  · 获取 PKList

                //List<Table> PKList = new List<Table>();
                //if (StaticDataList != null && StaticDataList.Count > 0)
                //{
                //    PKList = GetPKList(ConfigInfo.TableName);
                //}

                #endregion

                for (int i = 0; i < StaticDataList.Count; i++)
                {
                    if (!string.IsNullOrEmpty(StaticDataList[i].Comment))
                    {
                        //处理 注释 Simple
                        StaticDataList[i].CommentSimple = PublicHelper.SplitComment(StaticDataList[i].Comment);
                    }
                    else
                    {
                        StaticDataList[i].CommentSimple = "";
                    }
                    if (string.IsNullOrEmpty(StaticDataList[i].PropertyName))
                    {
                        StaticDataList[i].PropertyName = PublicHelper.GetPropertyName(StaticDataList[i].ColumnName);
                    }
                    //查找 主键
                    //StaticDataList[i].IsPK = PKList.Where(t => t.ColumnName == StaticDataList[i].ColumnName).Count() > 0;
                    //if (StaticDataList[i].IsPK.Value && StaticConfigInfo.PKName == null) //保存 主键 名称
                    //{
                    //    StaticConfigInfo.PKName = StaticDataList[i].ColumnName;
                    //}
                    //转成 Csharp 数据类型
                    StaticDataList[i].CsharpType = PublicHelper.MapCsharpType(StaticDataList[i].TypeName, StaticDataList[i].NotNUll);
                }

                //if (StaticConfigInfo.EventName != "CreateTable" && StaticConfigInfo.PKName.Length < 0)
                //{
                //    return "未获取到主键！";
                //}
                return string.Empty;
            }
            catch (Exception ex)
            {
                return "Exception:" + ex.Message;
            }
        }

        public string GenerateCode(List<ColumnInfo> DataList, ConfigInfo ConfigInfo)
        {
            if (!string.IsNullOrEmpty(ConfigInfo.EventName))
            {
                SetData(DataList, ConfigInfo);
                if (dicMethod.ContainsKey(ConfigInfo.EventName))
                {
                    var res = dicMethod[ConfigInfo.EventName].Invoke(this, null);
                    return res.ToString();
                }
                else
                {
                    MethodInfo method = GetType().GetMethod(ConfigInfo.EventName, new Type[] { });
                    if (method != null)
                    {
                        dicMethod[ConfigInfo.EventName] = method;
                        var res = method.Invoke(this, null);
                        return res.ToString();
                    }
                    return "ConfigInfo.EventName Error";
                }
            }
            return "ConfigInfo.EventName NULL";
        }

        private void PreCompile()
        {
            baseTemplatePath = Server.MapPath("~/Templates/");
            List<string> templates = new List<string> { "TplController.cshtml", "TplEditHtml.cshtml", "TplEditJs.cshtml", "TplInterface.cshtml", "TplListHtml.cshtml", "TplListJs.cshtml", "TplService.cshtml", "TplEntity.cshtml", "TplDto.cshtml" };
            foreach (var tplName in templates)
            {
                string tpl = System.IO.File.ReadAllText(baseTemplatePath + tplName);
                Razor.Compile(tpl, tplName);
            }
            IsCompiled = true;
        }

        #region · BuildEntity
        public string BuildEntity()
        {
            ColumnInfo Entity = new ColumnInfo();
            var ColList = StaticDataList.Where(t => t.IsDataColumn == true).ToList();
            //var ExtColList = StaticDataList.Where(t => t.IsDataColumn == false).ToList();
            string ModelFolderName = StaticConfigInfo.TableName.Split('_').Length > 0 ? StaticConfigInfo.TableName.Split('_')[0] : "Sys";
            ModelFolderName = ModelFolderName.Substring(0, 1).ToUpper() + ModelFolderName.Substring(1).ToLower();
            StaticConfigInfo.ModelFolderName = ModelFolderName;
            string tplName = "TplEntity.cshtml";
            string tplPath = baseTemplatePath + tplName;
            string tpl = System.IO.File.ReadAllText(tplPath);
            string content = Razor.Parse(tpl, new { ColList, ConfigInfo = StaticConfigInfo }, tplName);
            return content;
        }

        public string BuildDto()
        {
            ColumnInfo Entity = new ColumnInfo();
            var ColList = StaticDataList.Where(t => t.IsDataColumn == true).ToList();
            var SearchList = StaticDataList.Where(t => t.IsCondition == true).ToList();
            //var ExtColList = StaticDataList.Where(t => t.IsDataColumn == false).ToList();
            string ModelFolderName = StaticConfigInfo.TableName.Split('_').Length > 0 ? StaticConfigInfo.TableName.Split('_')[0] : "Sys";
            ModelFolderName = ModelFolderName.Substring(0, 1).ToUpper() + ModelFolderName.Substring(1).ToLower();
            StaticConfigInfo.ModelFolderName = ModelFolderName;
            string tplName = "TplDto.cshtml";
            string tplPath = baseTemplatePath + tplName;
            string tpl = System.IO.File.ReadAllText(tplPath);
            string content = Razor.Parse(tpl, new { ColList, SearchList, ConfigInfo = StaticConfigInfo }, tplName);
            return content;
        }
        #endregion

        #region · BuildService

        public string BuildBLL()
        {
            string ModelFolderName = StaticConfigInfo.TableName.Split('_').Length > 0 ? StaticConfigInfo.TableName.Split('_')[0] : "Sys";
            ModelFolderName = ModelFolderName.Substring(0, 1).ToUpper() + ModelFolderName.Substring(1).ToLower();
            StaticConfigInfo.ModelFolderName = ModelFolderName;
            string tplName = "TplService.cshtml";
            string tplPath = baseTemplatePath + tplName;
            string tpl = System.IO.File.ReadAllText(tplPath);
            string content = Razor.Parse(tpl, new { ConfigInfo = StaticConfigInfo }, tplName);
            return content;
        }

        public string BuildInterface()
        {
            string ModelFolderName = StaticConfigInfo.TableName.Split('_').Length > 0 ? StaticConfigInfo.TableName.Split('_')[0] : "Sys";
            ModelFolderName = ModelFolderName.Substring(0, 1).ToUpper() + ModelFolderName.Substring(1).ToLower();
            StaticConfigInfo.ModelFolderName = ModelFolderName;
            string tplName = "TplInterface.cshtml";
            string tplPath = baseTemplatePath + tplName;
            string tpl = System.IO.File.ReadAllText(tplPath);
            string content = Razor.Parse(tpl, new { ConfigInfo = StaticConfigInfo }, tplName);
            return content;
        }
        #endregion

        #region · BuildController

        public string BuildController()
        {
            string ModelFolderName = StaticConfigInfo.TableName.Split('_').Length > 0 ? StaticConfigInfo.TableName.Split('_')[0] : "Sys";
            ModelFolderName = ModelFolderName.Substring(0, 1).ToUpper() + ModelFolderName.Substring(1).ToLower();
            StaticConfigInfo.ModelFolderName = ModelFolderName;
            string tplName = "TplController.cshtml";
            string tplPath = baseTemplatePath + tplName;
            string tpl = System.IO.File.ReadAllText(tplPath);
            string content = Razor.Parse(tpl, new { ConfigInfo = StaticConfigInfo }, tplName);
            return content;
        }
        #endregion

        #region · BuildListHtml


        public string BuildListHtml()
        {
            var ColList = GetCommonList(StaticDataList);
            ColList = ColList.Where(t => t.IsShow == true).ToList();
            var SearchList = StaticDataList.Where(t => t.IsCondition == true).ToList();
            string ModelFolderName = StaticConfigInfo.TableName.Split('_').Length > 0 ? StaticConfigInfo.TableName.Split('_')[0] : "Sys";
            ModelFolderName = ModelFolderName.Substring(0, 1).ToUpper() + ModelFolderName.Substring(1).ToLower();
            StaticConfigInfo.ModelFolderName = ModelFolderName;
            string tplName = "TplListHtml.cshtml";
            string tplPath = baseTemplatePath + tplName;
            string tpl = System.IO.File.ReadAllText(tplPath);
            string content = Razor.Parse(tpl, new { ColList, ConfigInfo = StaticConfigInfo, SearchList }, tplName);
            return content;
        }

        #endregion

        #region · BuildEditHTML
        public string BuildEditHTML()
        {
            //ViewBag.Content = EditHtml();
            var ColList = GetCommonList(StaticDataList);
            string ModelFolderName = StaticConfigInfo.TableName.Split('_').Length > 0 ? StaticConfigInfo.TableName.Split('_')[0] : "Sys";
            ModelFolderName = ModelFolderName.Substring(0, 1).ToUpper() + ModelFolderName.Substring(1).ToLower();
            StaticConfigInfo.ModelFolderName = ModelFolderName;
            string tplName = "TplEditHtml.cshtml";
            string tplPath = baseTemplatePath + tplName;
            string tpl = System.IO.File.ReadAllText(tplPath);
            string content = Razor.Parse(tpl, new { ColList, ConfigInfo = StaticConfigInfo }, tplName);
            return content;
        }

        public List<ColumnInfo> GetCommonList(List<ColumnInfo> listCol)
        {
            return listCol.Where(t => !GetRemoveCols().Contains(t.ColumnName)).ToList();
        }
        #endregion

        #region · BuildEditJS

        public string BuildEditJS()
        {
            var ColList = GetCommonList(StaticDataList);
            string ModelFolderName = StaticConfigInfo.TableName.Split('_').Length > 0 ? StaticConfigInfo.TableName.Split('_')[0] : "Sys";
            ModelFolderName = ModelFolderName.Substring(0, 1).ToUpper() + ModelFolderName.Substring(1).ToLower();
            StaticConfigInfo.ModelFolderName = ModelFolderName;
            string tplName = "TplEditJs.cshtml";
            string tplPath = baseTemplatePath + tplName;
            string tpl = System.IO.File.ReadAllText(tplPath);
            string content = Razor.Parse(tpl, new { ColList, ConfigInfo = StaticConfigInfo }, tplName);
            return content;
        }

        #endregion

        #region · BuildListJS
        public string BuildListJS()
        {
            string ModelFolderName = StaticConfigInfo.TableName.Split('_').Length > 0 ? StaticConfigInfo.TableName.Split('_')[0] : "Sys";
            ModelFolderName = ModelFolderName.Substring(0, 1).ToUpper() + ModelFolderName.Substring(1).ToLower();
            StaticConfigInfo.ModelFolderName = ModelFolderName + "Manage";
            string tplName = "TplListJs.cshtml";
            string tplPath = baseTemplatePath + tplName;
            string tpl = System.IO.File.ReadAllText(tplPath);
            string content = Razor.Parse(tpl, new { ConfigInfo = StaticConfigInfo }, tplName);
            //ViewBag.content = content;
            return content;
        }
        #endregion

        #region · CreateTable
        public string CreateTable()
        {
            string SQLContent = PublicHelper.CreateTable(StaticDataList, StaticConfigInfo);
            return SQLContent;
        }
        #endregion

        #region · BuildMenuSql

        #endregion

        public List<string> GetRemoveCols()
        {
            if (removeCols == null)
            {
                removeCols = new ConfigHelper().ReadRemoveCols();
            }
            return removeCols;
        }

        public JsonResult UploadFile(HttpPostedFileBase pdmFile)
        {
            try
            {
                var arr = pdmFile.FileName.Split('.');
                var extName = arr[arr.Length - 1];
                if (pdmFile.ContentType != "application/octet-stream" && extName != "pdm")
                {
                    return Json(new { status = "Fail", message = "文件类型错误！" });
                }
                string fileName = pdmFile.FileName;
                string path = Server.MapPath("~/PdmFiles/" + fileName);
                pdmFile.SaveAs(path);
                return Json(new { status = "Success", message = "Success" });
            }
            catch (Exception ex)
            {
                return Json(new { status = "Error", message = ex.Message });
            }
        }

        private void WriteFile(string fileName, string content)
        {
            string path = Server.MapPath("~/BuildCodeOutPut/");
            if (!Directory.Exists(path))
            {
                Directory.CreateDirectory(path);
            }
            //using (StreamWriter sw = System.IO.File.AppendText(path + fileName))
            //{
            //    sw.Write(code);
            //}
            System.IO.File.AppendAllText(path + fileName, content);
        }
    }
}